/* Sokoban
 * HIT3243
 * Authors: Mike Blackney, Ben Ingarfield, Kurniawan
 */

#include "pawn.h"
#include "xfileentity.h"

Pawn::Pawn( int p_type, AiFunction *ai_funct,
		   LPDIRECT3DDEVICE9 device,
		   CXFileEntity *x_model, const D3DXVECTOR3& worldRatio,
		   float fx, float fy, float fz )
: type(p_type), ai(ai_funct),
  model(NULL), world(worldRatio),
  x(fx), y(fy), z(fz), rotation(0) {

	// If we've been given a 3d model, we should make a clone
	// of it for our own use:
	HRESULT hr;

	if (x_model) {
		V( x_model->Clone( device, model ) );
		assert(model);
	}

	// Now that the rest of init is done, reset the AI:
	if (ai) { 
		  ai->Reset( this );
		  ai->Position(x, y, z);
	}

}

Pawn::~Pawn( ) {
	delete model;
	delete ai;
}

HRESULT Pawn::Unload( ) {
	return S_OK;
}

void Pawn::Update ( double fTime, float fElapsedTime ) {
	// Call the AI function:
	if (NULL != ai) (*ai)( this, fTime, fElapsedTime );
}

#define X_SCALE 32
#define X_OFFSET 400
#define Y_SCALE 22
#define Y_OFFSET 150
#define Z_SCALE 40

void Pawn::Render3D( IDirect3DDevice9 *pd3dDevice, double fTime, float fElapsedTime ) const {

	// We're allowing NULL model references to exit
	// gracefully while we're developing:
	if (!model) return;

	static D3DXMATRIX transform;

	// Translate last:
	D3DXMatrixTranslation( &transform, y * world.y, z * world.z, x * world.x );

	// Rotate after (so before) translate:
	static D3DXVECTOR3 rotationaxis = D3DXVECTOR3(0,1,0);
	static D3DXMATRIX rotationmatrix;
	D3DXMatrixRotationAxis(&rotationmatrix, &rotationaxis, rotation);
	D3DXMatrixMultiply( &transform, &rotationmatrix, &transform );

	//Update the model's coordinates and animate:
	model->FrameMove( fElapsedTime, &transform );

	// Render the model:
	model->Render3d( );
}


bool Pawn::operator <( const Pawn &other ) const {
	return (x + y - (z/2)) < (other.x + other.y - (other.z/2));
}

void Pawn::ResetAi( ) {
	ai->Reset( this );
}

AiFunction *Pawn::GetAi( ) const {
	return ai;
}

void Pawn::SetAi( AiFunction *new_ai ) {
// NOTE: to be used carefully.  Doesn't delete old ai,
// so memory must be retained or deleted by caller.
	ai = new_ai;
}
